【41计划打卡-11】深度学习3-感知机
往期精彩:
开始之前做一发广告,我的一位学长开了知乎专栏,主写机器学习和统计学习方面的内容,有兴趣可以看看,有兴趣可以关注一下。下面是他第一篇文章的链接,
https://zhuanlan.zhihu.com/p/26596771
【本文唯一授权知乎专栏初学者KIRA的数学笔记】
前言
感知机,不严谨的说,可以看做是神经网络中的一个神经,用于接收、处理、传递信息的单元。在李航老师的《统计学习方法》中,将其解释为一种二分类的线性分类模型。在今天的篇章中将会介绍感知机。
原文链接是我在有道云笔记用markdown写的,这篇文章中涉及的代码将会放在我的github里面。https://github.com/ZBayes/Neural_Networks/tree/master/Peceptron
感知机初探
先是比较严格的定义,见下图:
以二维为例,一些点分布在一个平面直角坐标系内,这些点代表不同的个体,每个个体均属于-1或者1两类中的一个,感知机能找到一条直线,使得他们将平面分成两份,其中一侧是属于1,另一侧属于-1(当然了,知识满足最小误差)。如下图所示,找到条线,把红色和蓝色的分开。
找到这条线之后,当有新的点需要去判断属于哪一类时,只要计算该点在线的那一侧即可。
感知机使用的条件
其实非常简单,要另感知机生效,有较好的分类效果,这些点根据类-1和1的分布必须是线性可分的,要存在一条线令他们分开,才能去找。严格的定义如下:
但是,在计算之前,似乎没太多人去做这个判断,而是直接去训练感知机,如果结果怎么训练都不好,多半就是这个训练集线性不可分了。
感知机的训练方法
说是训练感知机,其实说白了就是求感知机里面你的两个参数,分别是w和b,于是问题就简单了,可以将问题根据损失函数最小化的无约束最优化问题解决。形式是这样的:
说说这个公式的构造,yi是实际值,而(w*xi+b)是预测值,yi只有两个值,1和-1,而分类器其实就是根据(w*xi+b)的正负性得到的,所以,两者如果同号,就表示分类正确,两者相乘为正,如果不同号则说明分类错误,两者相乘为负,换句话说,如果这两者相乘的结果越大,则说明分类越正确,反之亦然。求和说明把训练集内所有的样本都算出来,现在的公式是越大越好,前面加一个符号,就越小越好,于是,就有了上面的公式。
求解这个问题的方法就很多了,最速下降法,牛顿法,高级点的,遗传算法、模拟退火,粒子群之类的,都可以算(究其历史,其实“训练”这个词来源与计算机类专业的人,在数学中,喜欢叫做迭代或者粗暴的叫做计算,看来学术圈里面的神经网络和机器学习,能写一篇啊哈哈哈)。最常见的,应该就是随机梯度下降法了(Stochastic Gradient Descnt,SGD)。
随机梯度下降法
这个方法的核心其实就是最速下降法的变种,变在求最速下降方向时用的是随机取的一个样本求得的梯度方向。
此处不赘述最速下降法是啥,简单地说,就是一个瞎子在爬山,他要到山顶,那么他是按照最陡的方向走一步,然后再次判断最陡的地方,再走一步,直到到达山顶。(每步长度相同)
所以这个方法的关键就在于怎么求方向。
理论证明,最陡的方向就是梯度方向(负导数方向!)。因为需要求的而是w和 b,所以对上面的最优化问题,对w和b求偏导,有:
可以发现,这个梯度方向其实和y以及x的值有关,所以需要抽取错分类的x和y来计算上面的梯度,然后带入上面的梯度,求得迭代公式。
现随机取一个错分点yi,xi,则能用下面的方式求出新的w和b。
根据新的w和b,继续进行分类,随机拿出错分点继续算,如此迭代,最终得到最优解。严格地,其迭代过程如下:
代码实现
代码实现或运算
这里主要用python,python虽然有些人没学过,但是我相信,python这种比较高级的、接近人类自然语言的计算机语言大家应该能看懂。网址来源是这位老师。链接是:http://blog.csdn.net/amira_von/article/details/50934028
# -*- coding: utf-8 -*-
"""
Created on Sat Mar 19 13:49:04 2016
@author: fengxinhe
"""
import copy
from matplotlib import pyplot as pl
from matplotlib import animation as ani
w=[0,0] #weight vector
b=0 #bias
yita=0.5 #learning rate
data=[[(1,1),1],[(1,-1),1],[(-1,1), 1], [(-1,-1), -1]]
record=[]
"""
if y(wx+b)<=0,return false; else, return true
"""
def sign(vec):
global w,b
res=0
res=vec[1]*(w[0]*vec[0][0]+w[1]*vec[0][1]+b)
if res>0: return 1
else: return -1
"""
update the paramaters w&b
"""
def update(vec):
global w,b,record
w[0]=w[0]+yita*vec[1]*vec[0][0]
w[1]=w[1]+yita*vec[1]*vec[0][1]
b=b+yita*vec[1]
record.append([copy.copy(w),b])
"""
check and calculate the whole data one time
if all of the input data can be classfied correctly at one time,
we get the answer
"""
def perceptron():
count=1
for ele in data:
flag=sign(ele)
if not flag>0:
count=1
update(ele)
else:
count+=1
if count>=len(data):
return 1
if __name__ == "__main__":
while 1:
if perceptron() > 0:
break
print record
x1=[]
y1=[]
x2=[]
y2=[]
#display the animation of the line change in searching process
fig = pl.figure()
ax = pl.axes(xlim=(-2, 2), ylim=(-2, 2))
line,=ax.plot([],[],'g',lw=2)
def init():
line.set_data([],[])
for p in data:
if p[1]>0:
x1.append(p[0][0])
y1.append(p[0][1])
else:
x2.append(p[0][0])
y2.append(p[0][1])
pl.plot(x1,y1,'or')
pl.plot(x2,y2,'ob')
return line,
def animate(i):
global record,ax,line
w=record[i][0]
b=record[i][1]
x1=-5
y1=-(b+w[0]*x1)/w[1]
x2=6
y2=-(b+w[0]*x2)/w[1]
line.set_data([x1,x2],[y1,y2])
return line,
animat=ani.FuncAnimation(fig,animate,init_func=init,frames=len(record),interval=1000,repeat=True,
blit=True)
pl.show()
我努力地找了一下,似乎没看到比较靠谱的py的感知机包,然而并没有。上面的就当做一个示例吧~
线性可分问题的解释
这里,我还是比较喜欢matlab的可视化,所以用下面的代码来画画逻辑或和逻辑异或的点的分布。
% ORx1=[1,1;1,-1;-1,1];
x2=[-1,-1];
subplot(1,2,1)
hold on
axis([-2,2,-2,2])
plot(x1(:,1),x1(:,2),'b*')
plot(x2(:,1),x2(:,2),'g*')
hold off% XORx1=[1,1;-1,-1];
x2=[-1,1;1,-1];
subplot(1,2,2)
hold on
axis([-2,2,-2,2])
plot(x1(:,1),x1(:,2),'b*')
plot(x2(:,1),x2(:,2),'g*')
hold off
画出来的图像是这样的:
左边的是或的图像,可以看到很明显可以找到一条线,能区分不同标记的点,相反,右边的异或是找不到这样的一条线的,所以并不能用感知机描述异或。
感知机不能解决线性可分问题,那么有两个思路,一个是将点投射到新的空间,或者把分类的直线转为曲线,这是非线性支持向量机的思想,另外一个思路就是,一个不行,那就两个感知机,那便是现在非常流行的神经网络!
参考文献
李航. 统计学习方法
吴岸城. 神经网络与深度学习
FXH_94. 感知机Python实现
QQ:545281848